package com.bosssoft.boss_exam_web.Controller;


import com.bosssoft.boss_exam_core.enums.ResultCode;
import com.bosssoft.boss_exam_core.exception.*;
import com.bosssoft.boss_exam_core.util.common.RandomUtil;
import com.bosssoft.boss_exam_core.util.web.ResponseUtil;
import com.bosssoft.boss_exam_core.validator.Order;
import com.bosssoft.boss_exam_core.validator.Sort;
import com.bosssoft.boss_exam_db.entity.*;
import com.bosssoft.boss_exam_db.model.DTO.RandomPaperDTO;
import com.bosssoft.boss_exam_db.model.vo.ExamPaperIsSubmitVO;
import com.bosssoft.boss_exam_db.model.vo.ExamPaperVO;
import com.bosssoft.boss_exam_db.model.vo.GeneratePaperVO;
import com.bosssoft.boss_exam_db.service.busines.*;
import com.bosssoft.boss_exam_web.common.annotation.LoginAdmin;
import com.bosssoft.boss_exam_web.common.annotation.LoginApplicant;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@Validated
@Slf4j
@Api(value="试卷控制器")
public class ExamPaperController {

    //注入试卷服务
    @Autowired
    private ExamPaperService examPaperService;

    //注入管理员服务
    @Autowired
    private AdminService adminService;

    //注入问题服务
    @Autowired
    private QuestionService questionService;

    //注入题型服务
    @Autowired
    private QuestionTypeService questionTypeService;

    // 注入试卷-问题服务
    @Autowired
    private ExamPaperQuestionService examPaperQuestionService;

    // 注入考试-试卷服务
    @Autowired
    private ExamExamPaperService examExamPaperService;

    @ApiOperation(value = "试卷查询", notes = "可根据试卷名称查询试卷", httpMethod = "GET", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examPaperName", value = "试卷名称", dataType = "String", required = false, dataTypeClass = String.class),
            @ApiImplicitParam(name = "openFlag", value = "开发标志", dataType = "String", required = false, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "jobId", value = "岗位ID", dataType = "String", required = false, dataTypeClass = String.class),
            @ApiImplicitParam(name = "page", value = "当前页码", dataType = "String", required = false, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "limit", value = "每页显示条数", dataType = "String", required = false, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "sort", value = "排序依据", dataType = "String", required = false, dataTypeClass = String.class),
            @ApiImplicitParam(name = "order", value = "排序方式", dataType = "String", required = false, dataTypeClass = String.class)
    })
    @GetMapping("/admin/examPaper/list")
    public Object list(@LoginAdmin String adminId,
                       @RequestParam String examPaperName,
                       @RequestParam Integer openFlag,
                       @RequestParam String jobId,
                       @RequestParam(defaultValue = "1") Integer page,
                       @RequestParam(defaultValue = "10") Integer limit,
                       @Sort @RequestParam(defaultValue = "add_time") String sort,
                       @Order @RequestParam(defaultValue = "desc") String order) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        //查询当前用户所在公司
        Company company = adminService.selectAdminBelongCompany(adminId);
        if(company==null){
            log.error("【严重警告】该管理员没有公司");
            throw new BusinessException("该管理员，没有归属公司");
        }
        PageInfo<ExamPaperIsSubmitVO> examPaperIsSubmitVOPageInfo = examPaperService.queryByCondition(company, examPaperName, jobId, openFlag, page, limit, sort, order);
        if (examPaperIsSubmitVOPageInfo == null) {
            log.error("【业余错误】，查询pageInfo为空");
            throw new QueryDataException();
        } else {
            Map<String, Object> data = new HashMap<>();
            data.put("total", examPaperIsSubmitVOPageInfo.getTotal());
            data.put("items", examPaperIsSubmitVOPageInfo.getList());
            return ResponseUtil.ok(data);
        }
    }

    @ApiOperation(value = "试卷添加", notes = "添加试卷", httpMethod = "POST", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examPaper", value = "试卷对象json", dataType = "ExamPaper", required = true, dataTypeClass = ExamPaper.class),
    })
    @PostMapping("/admin/examPaper/create")
    public Object create(@LoginAdmin String adminId, @RequestBody ExamPaper examPaper) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        Company company = adminService.selectAdminBelongCompany(adminId);
        examPaper.setCompanyId(company.getId());
        int recordNum = examPaperService.saveNotNull(examPaper);
        if (recordNum == 1) {
            return ResponseUtil.ok(examPaper);
        } else {
            log.error("【系统错误】 保存试卷失败");
            throw new UpdateEntityException();
        }
    }

    @ApiOperation(value = "试卷详细信息查询", notes = "可根据试卷的ID查询详情", httpMethod = "GET", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "试卷ID", dataType = "String", required = true, dataTypeClass = String.class),
    })
    @GetMapping("/admin/examPaper/detail/{id}")
    public Object read(@LoginAdmin String adminId, @PathVariable String id) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        List<ExamPaperVO> examPaperVOS = null;
        try {
            examPaperVOS = examPaperService.selectAllQuestion(id);
        } catch (Exception e) {
            log.error("【业务错误】 读取试卷异常" + e);
            throw new QueryDataException();
        }
        return ResponseUtil.ok(examPaperVOS);
    }

    @ApiOperation(value = "试卷更新", notes = "更新试卷", httpMethod = "POST", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examPaper", value = "试卷对象json，必须携带试卷ID", dataType = "ExamPaper", required = true, dataTypeClass = ExamPaper.class),
    })
    @PostMapping("/admin/examPaper/update")
    public Object update(@LoginAdmin String adminId, @RequestBody ExamPaper examPaper) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        int recordNum = examPaperService.updateNotNull(examPaper);
        if (recordNum == 1) {
            return ResponseUtil.ok(examPaper);
        } else {
            log.error("【系统错误】 保存试卷失败");
            throw new UpdateEntityException();
        }
    }

    @ApiOperation(value = "试卷删除", notes = "可根据试卷的ID逻辑删除试卷", httpMethod = "POST", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "试卷ID，非空", dataType = "String", required = true, dataTypeClass = String.class),
    })
    @PostMapping("/admin/examPaper/delete")
    public Object delete(@LoginAdmin String adminId, @RequestParam String id) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        ExamPaper examPaper = new ExamPaper();
        examPaper.setId(id);
        Boolean result=false;
        try {
            result=examPaperService.deleteForCascade(examPaper);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            log.error("【系统错误】 反射操作异常" + e);
            throw new ReflectionException(ResultCode.SYSTEM_INNER_ERROR);
        } catch (Exception e) {
            log.info("【业务错误】 逻辑删除试卷异常" + e);
            throw new DeleteEntityException();
        }
        if(result){
            return ResponseUtil.ok();
        }
        return ResponseUtil.fail(400,"删除试卷成功");
    }


    // fixme 遗忘了需要带上公司ID，查询该公司下的题型
    private List<Map<String, Object>> queryQuestionTypeMapList() {
        return questionTypeService.queryQuestionTypeMapList();
    }

    @ApiOperation(value = "试卷生成预览", notes = "可根据前台的组卷方式进行组卷", httpMethod = "POST", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "generatePaperVOS", value = "组卷配方", dataType = "GeneratePaperVO []", required = true, dataTypeClass = GeneratePaperVO[].class),
    })
    @PostMapping("/admin/examPaper/generatePaper")
    public Object generatePaper(@LoginAdmin String adminId, @RequestBody GeneratePaperVO[] generatePaperVOS) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        Company company = adminService.selectAdminBelongCompany(adminId);
        if(company==null){
            log.error("【严重警告】该管理员没有公司");
            throw new BusinessException("该管理员，没有归属公司");
        }
        RandomPaperDTO randomPaperDTO = new RandomPaperDTO();
        //查询公司的题型MAP
        List<Map<String, Object>> maps = queryQuestionTypeMapList();
        randomPaperDTO.setQuestionTypeMapList(maps);
        if (generatePaperVOS != null && generatePaperVOS.length != 0) {
            //用于存储某个类型题目的包装对象的容器 结构形如[ {questionTypeId:'',orderNum:'',questionList:[]} ]
            ArrayList<RandomPaperDTO.QuestionTypeOrderNum> questionTypeOrderNumList = new ArrayList<>();
            //遍历条件组
            for (GeneratePaperVO generatePaperVO : generatePaperVOS) {
                // 查询符合该条件的题目ID列表
                List<String> questionIds = questionService.queryQuestionForGreneratePaper(company, generatePaperVO);
                if (questionIds == null || questionIds.size() == 0) {
                    return ResponseUtil.fail(400, "没有这种组合的题目");
                }
                // 随机抽取指定条数的符合条件的题目ID
                ArrayList<String> selectIds = new ArrayList<>();
                for (int i = 0; i < generatePaperVO.getQuestionNum(); i++) {
                    String id = RandomUtil.RandomFile(questionIds);
                    selectIds.add(id);
                }
                //查询题目所有字段
                List<Question> questionList = questionService.queryQuestionBySomeIds(selectIds);
                //用于承载某个类型的题目
                RandomPaperDTO.QuestionTypeOrderNum questionTypeOrderNum = new RandomPaperDTO.QuestionTypeOrderNum();
                //问题类型
                String questionTypeId = generatePaperVO.getQuestionTypeId();
                //查询题型的优先级数
                QuestionType questionType = null;
                try {
                    questionType = questionTypeService.selectByKey(questionTypeId);
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    log.error("【系统错误】 反射操作异常" + e);
                    throw new ReflectionException(ResultCode.SYSTEM_INNER_ERROR);
                } catch (Exception e) {
                    log.info("【业务错误】 逻辑删除试卷异常" + e);
                    throw new DeleteEntityException();
                }
                //封装QuestionTypeOrderNum
                if (questionType != null) {
                    Integer orderNum = questionType.getOrderNum();
                    String questionTypeName = questionType.getName();
                    questionTypeOrderNum.setQuestionTypeId(questionTypeId);
                    questionTypeOrderNum.setQuestionTypeName(questionTypeName);
                    questionTypeOrderNum.setOrderNum(orderNum);
                }
                questionTypeOrderNum.setQuestionList(questionList);
                //如果是同类型的则将题目放到同一个RandomPaperDTO.QuestionTypeOrderNum对象的questionlist中
                List<RandomPaperDTO.QuestionTypeOrderNum> tempList = questionTypeOrderNumList.stream().filter(item -> item.getQuestionTypeId().equals(questionTypeId)).collect(Collectors.toList());
                if (tempList != null && tempList.size() != 0) {
                    RandomPaperDTO.QuestionTypeOrderNum questionTypeOrderNum1 = tempList.get(0);
                    // 同一个类型进行合并
                    questionTypeOrderNum1.getQuestionList().addAll(questionList);
                } else {
                    questionTypeOrderNumList.add(questionTypeOrderNum);
                }
            }
            ;
            randomPaperDTO.setQuestionTypeOrderNumList(questionTypeOrderNumList);
        }
        return ResponseUtil.ok(randomPaperDTO);
    }


    @ApiOperation(value = "存储试卷题目 ", notes = "试卷对应的题目批量存储", httpMethod = "POST", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examPaperQuestionList", value = "试卷题目实体", dataType = " List<ExamPaperQuestion>", required = true, dataTypeClass = List.class),
    })
    @PostMapping("/admin/examPaper/submitPaperQuestion")
    public Object insertPaperQuestions(@LoginAdmin String adminId, @RequestBody List<ExamPaperQuestion> examPaperQuestionList) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        Company company = adminService.selectAdminBelongCompany(adminId);
        if(company==null){
            log.error("【严重警告】该管理员没有公司");
            throw new BusinessException("该管理员，没有归属公司");
        }
        Integer resultFlag = examPaperQuestionService.insertPaperQuestions(company.getId(), examPaperQuestionList);
        if (resultFlag == 1) {
            return ResponseUtil.ok();
        }
        return ResponseUtil.fail(400, "操作失败");
    }

    @ApiOperation(value = "查询试卷详情 ", notes = "根据试卷的ID查询试卷的所有试题", httpMethod = "GET", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "getExamPaperDetail", value = "试卷题目实体", dataType = " String", required = true, dataTypeClass = String.class),
    })
    @PostMapping("/admin/examPaper/examPaperDetail")
    public Object getExamPaperDetail(@LoginAdmin String adminId, @RequestParam String id) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        Company company = adminService.selectAdminBelongCompany(adminId);
        RandomPaperDTO randomPaperDTO = new RandomPaperDTO();
        //查询多有的题型MAP  注：公用生成卷子的数据封装结构RandomPaperDTO
        List<Map<String, Object>> maps = this.queryQuestionTypeMapList();

        randomPaperDTO.setQuestionTypeMapList(maps);
        List<RandomPaperDTO.QuestionTypeOrderNum> questionTypeOrderNums= examPaperService.queryExamPaperQuestionDetail(company.getId(),id,maps);
        //用于存储某个类型题目的包装对象的容器 结构形如[ {questionTypeId:'',orderNum:'',questionList:[]} ]
        randomPaperDTO.setQuestionTypeOrderNumList(questionTypeOrderNums);
        return ResponseUtil.ok(questionTypeOrderNums);
    }

    @ApiOperation(value = "查询试卷详情 ", notes = "根据试卷的ID查询试卷的所有试题", httpMethod = "GET", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examId", value = "考试ID", dataType = " String", required = true, dataTypeClass = String.class),
    })
    @GetMapping("/phone/examPaper/examPaperDetail")
    public Object getPhoneExamPaper(@LoginApplicant String applicantId,@RequestParam String examId) {
        if (applicantId == null) {
            return ResponseUtil.unlogin();
        }
        // 根据考试ID查询试卷ID
        List<ExamExamPaper> examExamPapers = examExamPaperService.queryExamPaperByExamId(examId);
        String examPaperId=null;
        if(examExamPapers!=null && examExamPapers.size()!=0){
            examPaperId = examExamPapers.get(0).getExamPaperId();
        }
        RandomPaperDTO randomPaperDTO = new RandomPaperDTO();
        //查询多有的题型MAP  注：公用生成卷子的数据封装结构RandomPaperDTO
        List<Map<String, Object>> maps = this.queryQuestionTypeMapList();
        randomPaperDTO.setQuestionTypeMapList(maps);
        List<RandomPaperDTO.QuestionTypeOrderNum> questionTypeOrderNums= examPaperService.queryExamPaperQuestionDetail(examPaperId,maps);
        //用于存储某个类型题目的包装对象的容器 结构形如[ {questionTypeId:'',orderNum:'',questionList:[]} ]
        randomPaperDTO.setQuestionTypeOrderNumList(questionTypeOrderNums);
        return ResponseUtil.ok(questionTypeOrderNums);
    }

    @ApiOperation(value = "查询试卷详情 ", notes = "根据试卷的ID查询试卷的所有试题", httpMethod = "GET", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "getExamPaperDetail", value = "试卷题目实体", dataType = " String", required = true, dataTypeClass = String.class),
    })
    @PostMapping("/pc/examPaper/examPaperDetail")
    public Object getPCExamPaper(@LoginApplicant String applicantId,@RequestParam String id) {
        if (applicantId == null) {
            return ResponseUtil.unlogin();
        }
        RandomPaperDTO randomPaperDTO = new RandomPaperDTO();
        //查询多有的题型MAP  注：公用生成卷子的数据封装结构RandomPaperDTO
        List<Map<String, Object>> maps = this.queryQuestionTypeMapList();
        randomPaperDTO.setQuestionTypeMapList(maps);
        List<RandomPaperDTO.QuestionTypeOrderNum> questionTypeOrderNums= examPaperService.queryExamPaperQuestionDetail(id,maps);
        //用于存储某个类型题目的包装对象的容器 结构形如[ {questionTypeId:'',orderNum:'',questionList:[]} ]
        randomPaperDTO.setQuestionTypeOrderNumList(questionTypeOrderNums);
        return ResponseUtil.ok(questionTypeOrderNums);
    }

    @ApiOperation(value = "查询试卷", notes = "根据考试ID查询试卷", httpMethod = "GET", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examId", value = "考试ID", dataType = " String", required = true, dataTypeClass = String.class),
    })
    @PostMapping("/phone/examPaper/queryExamPaperByExamId")
    public Object queryExamPaperByExamId(@LoginApplicant String applicantId,@RequestParam String examId) {
        if (applicantId == null) {
            return ResponseUtil.unlogin();
        }
        List<ExamExamPaper> examExamPapers =examPaperService.queryExamPaperByExamId(examId);
        if(examExamPapers!=null&& examExamPapers.size()>0){
            return ResponseUtil.ok(examExamPapers.get(0).getExamPaperId());
        }
        return ResponseUtil.ok();
    }
}
